{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"https://raw.githubusercontent.com/Qiskit/qiskit-tutorials/master/images/qiskit-heading.png\" alt=\"Note: In order for images to show up in this jupyter notebook you need to select File => Trusted Notebook\" width=\"500 px\" align=\"left\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## _*Winning The Game of Magic Square with Quantum Pseudo-Telepathy *_ \n",
    "\n",
    "The latest version of this notebook is available on https://github.com/QISKit/qiskit-tutorial.\n",
    "***\n",
    "### Contributors\n",
    "Rudy Raymond\n",
    "\n",
    "### Qiskit Package Versions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'qiskit': '0.10.3',\n",
       " 'qiskit-terra': '0.8.1',\n",
       " 'qiskit-ignis': '0.1.1',\n",
       " 'qiskit-aer': '0.2.1',\n",
       " 'qiskit-ibmq-provider': '0.2.2',\n",
       " 'qiskit-aqua': '0.5.1'}"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import qiskit\n",
    "qiskit.__qiskit_version__"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Introduction\n",
    "\n",
    "We have seen that quantum entanglement enables phenomena that we often see in science fiction, such as, (quantum) teleportation. Now, we will see that it can give rise to a kind of telepathy between two separated parties. Well, strictly speaking, quantum entanglement does not allow communication. However, it can be used for [Quantum Pseudo-Telepathy](https://en.wikipedia.org/wiki/Quantum_pseudo-telepathy), that is, parties sharing entangled states can be seen as if having some kind of communication to outside observers. \n",
    "\n",
    "Here, we consider [the Magic Square Game](https://en.wikipedia.org/wiki/Quantum_pseudo-telepathy), which is also known as *The Mermin-Peres Magic Square Game*. The magic square is a $3\\times 3$ matrix whose entries are either $0$ or $1$ such that the sum of each row is even, and the sum of each column is odd. Notice that such *magic* square is impossible: because there are odd number of entries, the sum of rows implies that the sum of $1$s must be even, but the sum of columns implies that it must be odd. A contradiction. \n",
    "\n",
    "The magic square game is played by a referee against two distant parties, say, Alice and Bob. In the game, the referee sends an integer $a \\in \\{1,2,3\\}$ to Alice who must answer with the $a$-th row of the magic square, and an integer $b \\in \\{1,2,3\\}$ to Bob, who must return the $b$-th column of the magic square. Alice and Bob win the game if the sum of entries of Alice's answer is even, the sum of Bob's answer is odd, and their intersecting answer is the same. Otherwise, the referee wins. Prior to the start of the game, Alice and Bob can meet to discuss their strategy and/or share random bits and entangled states, but they are not allowed to communicate during the game.\n",
    "\n",
    "For example, a simple strategy for Alice and Bob is to answer to the referee according to the following $3x3$ Boolean matrix:\n",
    "\n",
    "$$\n",
    "\\begin{pmatrix}\n",
    "1 & 1 & 0\\\\\n",
    "0 & 1 & 1\\\\\n",
    "0 & 1 & ?\n",
    "\\end{pmatrix}.\n",
    "$$\n",
    "\n",
    "That is, for $a = 1$ and $b = 2$, Alice's answer is $110$, while Bob's is $111$ and they win. However, they lose when the referee sends them $a = 3$ and $b=3$, because Alice's and Bob's answers do not satisfy the requirement. It can be shown that in the classical setting the winning probability of Alice and Bob is at most $8/9$ (in the above example, there are eight out of nine combinations of $a$ and $b$ that result in Alice and Bob winning the game).     \n",
    "\n",
    "\n",
    "## Quantum Winning Strategy\n",
    "\n",
    "However, with shared quantum states Alice and Bob can always win the game regardless of the values of $a$ and $b$. We show the winning strategy following [Brassard, Broadbent, and Tapp, 2004](https://arxiv.org/abs/quant-ph/0407221).\n",
    "\n",
    "### Preparing the environment\n",
    "First, as usual we prepare the environment. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# useful additional packages \n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "\n",
    "# useful math functions\n",
    "from math import pi, cos, acos, sqrt\n",
    "import random\n",
    "\n",
    "# importing the QISKit\n",
    "from qiskit import Aer, IBMQ, execute\n",
    "from qiskit.providers.ibmq import least_busy\n",
    "from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit\n",
    "from qiskit.tools.visualization import plot_histogram"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# To use IBMQ online backends\n",
    "IBMQ.load_accounts()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sharing entangled quantum states\n",
    "\n",
    "Prior to the start of the game, Alice and Bob share the following quantum state. The first two qubits go to Alice, and the rest to Bob. \n",
    "\n",
    "$$\n",
    "|\\psi\\rangle = \\frac{1}{2}|0011\\rangle - \\frac{1}{2}|0110\\rangle - \\frac{1}{2}|1001\\rangle + \\frac{1}{2}|1100\\rangle\n",
    "$$\n",
    "\n",
    "To generate such quantum state, we first prepare $4$ qubits and the corresponding $4$ classical bits to record the measurement later. Below is a quantum circuit to create the above entangled state."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "N = 4\n",
    "# Creating registers\n",
    "qr = QuantumRegister(N, name=\"qr\")\n",
    "\n",
    "# for recording the measurement on qr\n",
    "cr = ClassicalRegister(N, name=\"cr\")\n",
    "\n",
    "circuitName = 'sharedEntangled'\n",
    "sharedEntangled = QuantumCircuit(qr, cr, name=circuitName)\n",
    "\n",
    "#Create uniform superposition of all strings of length 2\n",
    "for i in range(2):\n",
    "    sharedEntangled.h(qr[i])\n",
    "\n",
    "#The amplitude is minus if there are odd number of 1s\n",
    "for i in range(2):\n",
    "    sharedEntangled.z(qr[i])\n",
    "\n",
    "#Copy the content of the fist two qubits to the last two qubits\n",
    "for i in range(2):\n",
    "    sharedEntangled.cx(qr[i], qr[i+2])\n",
    "\n",
    "#Flip the last two qubits\n",
    "for i in range(2,4):\n",
    "    sharedEntangled.x(qr[i])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Alice's and Bob's operations\n",
    "\n",
    "Receiving $a \\in \\{1,2,3\\}$, Alice applies the unitary matrix $A_a$ on her qubits, where $A_a$ is one of the followings:\n",
    "\n",
    "$$\n",
    "A_1 = \\frac{1}{\\sqrt{2}}\n",
    "\\begin{pmatrix}\n",
    "i & 0 & 0 & 1\\\\\n",
    "0 & -i& 1 & 0\\\\\n",
    "0 & i & 1 & 0\\\\\n",
    "1 & 0 & 0 & i\n",
    "\\end{pmatrix},~\n",
    "A_2 = \\frac{1}{2}\n",
    "\\begin{pmatrix}\n",
    "i & 1 & 1 & i\\\\\n",
    "-i& 1 &-1 & i\\\\\n",
    "i & 1 &-1 &-i\\\\\n",
    "-i& 1 & 1 &-i\n",
    "\\end{pmatrix},~\n",
    "A_3 = \\frac{1}{2}\n",
    "\\begin{pmatrix}\n",
    "-1&-1&-1& 1\\\\\n",
    "1 & 1&-1& 1\\\\\n",
    "1 &-1& 1& 1\\\\\n",
    "1 &-1&-1&-1\n",
    "\\end{pmatrix}\n",
    "$$\n",
    "\n",
    "Meanwhile, receiving $b \\in \\{1,2,3\\}$, Bob applies the unitary matrix $B_b$ on his qubits, where $B_b$ is one of the followings:\n",
    "\n",
    "$$\n",
    "B_1 = \\frac{1}{2}\n",
    "\\begin{pmatrix}\n",
    " i&-i& 1& 1\\\\\n",
    "-i&-i& 1&-1\\\\\n",
    " 1& 1&-i& i\\\\\n",
    "-i& i& 1& 1\n",
    "\\end{pmatrix},~\n",
    "B_2 = \\frac{1}{2}\n",
    "\\begin{pmatrix}\n",
    "-1& i& 1& i\\\\\n",
    " 1& i& 1&-i\\\\\n",
    " 1&-i& 1& i\\\\\n",
    "-1&-i& 1&-i\n",
    "\\end{pmatrix},~\n",
    "B_3 = \\frac{1}{\\sqrt{2}}\n",
    "\\begin{pmatrix}\n",
    " 1& 0 & 0 & 1\\\\\n",
    "-1& 0 & 0 & 1\\\\\n",
    "0 & 1 & 1 & 0\\\\\n",
    "0 & 1 &-1 & 0\n",
    "\\end{pmatrix}\n",
    "$$\n",
    "\n",
    "After applying their unitary operators, Alice and Bob independently measure their qubits in the computational basis and use the outcome as the answer to their first two bits, while their third bits can be inferred from the parity with each of their first two bits: even for Alice and odd for Bob.\n",
    "\n",
    "Below are the circuits of Alice's and Bob's operations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "#we first define controlled-u gates required to assign phases \n",
    "from math import pi\n",
    "def ch(qProg, a, b):\n",
    "    \"\"\" Controlled-Hadamard gate \"\"\"\n",
    "    qProg.h(b)\n",
    "    qProg.sdg(b)\n",
    "    qProg.cx(a, b)\n",
    "    qProg.h(b)\n",
    "    qProg.t(b)\n",
    "    qProg.cx(a, b)\n",
    "    qProg.t(b)\n",
    "    qProg.h(b)\n",
    "    qProg.s(b)\n",
    "    qProg.x(b)\n",
    "    qProg.s(a)\n",
    "    return qProg\n",
    "\n",
    "def cu1pi2(qProg, c, t):\n",
    "    \"\"\" Controlled-u1(phi/2) gate \"\"\"\n",
    "    qProg.u1(pi/4.0, c)\n",
    "    qProg.cx(c, t)\n",
    "    qProg.u1(-pi/4.0, t)\n",
    "    qProg.cx(c, t)\n",
    "    qProg.u1(pi/4.0, t)\n",
    "    return qProg\n",
    "\n",
    "def cu3pi2(qProg, c, t):\n",
    "    \"\"\" Controlled-u3(pi/2, -pi/2, pi/2) gate \"\"\"\n",
    "    qProg.u1(pi/2.0, t)\n",
    "    qProg.cx(c, t)\n",
    "    qProg.u3(-pi/4.0, 0, 0, t)\n",
    "    qProg.cx(c, t)\n",
    "    qProg.u3(pi/4.0, -pi/2.0, 0, t)\n",
    "    return qProg"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The last two gates will be used to assign amplitudes with $i$ phase and realize the following unitaries: \n",
    "\n",
    "$$\n",
    "U_\\mbox{cu1pi2} = \n",
    "\\begin{pmatrix}\n",
    "1 & 0 & 0 & 0\\\\\n",
    "0 & 1 & 0 & 0\\\\\n",
    "0 & 0 & 1 & 0\\\\\n",
    "0 & 0 & 0 & i\n",
    "\\end{pmatrix},~\n",
    "U_\\mbox{cu3pi2} = \\frac{1}{\\sqrt{2}}\n",
    "\\begin{pmatrix}\n",
    "\\sqrt{2} & 0 & 0 & 0\\\\\n",
    "0 & \\sqrt{2} & 0 & 0\\\\\n",
    "0 & 0 & 1 & -i\\\\\n",
    "0 & 0 & -i & 1\n",
    "\\end{pmatrix}\n",
    "$$\n",
    "\n",
    "Next, we define circuits used by Alice and Bob for each of their inputs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# dictionary for Alice's operations/circuits\n",
    "aliceCircuits = {}\n",
    "# Quantum circuits for Alice when receiving idx in 1, 2, 3\n",
    "for idx in range(1, 4):\n",
    "    circuitName = \"Alice\"+str(idx)\n",
    "    aliceCircuits[circuitName] = QuantumCircuit(qr, cr, name=circuitName)\n",
    "    theCircuit = aliceCircuits[circuitName]\n",
    "    \n",
    "    if idx == 1:\n",
    "        #the circuit of A_1\n",
    "        theCircuit.x(qr[1])\n",
    "        theCircuit.cx(qr[1], qr[0])\n",
    "        theCircuit = cu1pi2(theCircuit, qr[1], qr[0])\n",
    "        theCircuit.x(qr[0])\n",
    "        theCircuit.x(qr[1])\n",
    "        theCircuit = cu1pi2(theCircuit, qr[0], qr[1])\n",
    "        theCircuit.x(qr[0])\n",
    "        theCircuit = cu1pi2(theCircuit, qr[0], qr[1])\n",
    "        theCircuit = cu3pi2(theCircuit, qr[0], qr[1])\n",
    "        theCircuit.x(qr[0])\n",
    "        theCircuit = ch(theCircuit, qr[0], qr[1])\n",
    "        theCircuit.x(qr[0])\n",
    "        theCircuit.x(qr[1])\n",
    "        theCircuit.cx(qr[1], qr[0])\n",
    "        theCircuit.x(qr[1])\n",
    "        \n",
    "    elif idx == 2:\n",
    "        theCircuit.x(qr[0])\n",
    "        theCircuit.x(qr[1])\n",
    "        theCircuit = cu1pi2(theCircuit, qr[0], qr[1])\n",
    "        theCircuit.x(qr[0])\n",
    "        theCircuit.x(qr[1])\n",
    "        theCircuit = cu1pi2(theCircuit, qr[0], qr[1])\n",
    "        theCircuit.x(qr[0])\n",
    "        theCircuit.h(qr[0])\n",
    "        theCircuit.h(qr[1])\n",
    "\n",
    "    elif idx == 3:\n",
    "        theCircuit.cz(qr[0], qr[1])\n",
    "        theCircuit.swap(qr[0], qr[1])\n",
    "        theCircuit.h(qr[0])\n",
    "        theCircuit.h(qr[1])\n",
    "        theCircuit.x(qr[0])\n",
    "        theCircuit.x(qr[1])\n",
    "        theCircuit.cz(qr[0], qr[1])\n",
    "        theCircuit.x(qr[0])\n",
    "        theCircuit.x(qr[1])\n",
    "        \n",
    "    #measure the first two qubits in the computational basis\n",
    "    theCircuit.measure(qr[0], cr[0])\n",
    "    theCircuit.measure(qr[1], cr[1])\n",
    "\n",
    "# dictionary for Bob's operations/circuits\n",
    "bobCircuits = {}\n",
    "# Quantum circuits for Bob when receiving idx in 1, 2, 3\n",
    "for idx in range(1,4):\n",
    "    circuitName = \"Bob\"+str(idx)\n",
    "    bobCircuits[circuitName] = QuantumCircuit(qr, cr, name=circuitName)\n",
    "    theCircuit = bobCircuits[circuitName]\n",
    "    if idx == 1:\n",
    "        theCircuit.x(qr[2])\n",
    "        theCircuit.x(qr[3])\n",
    "        theCircuit.cz(qr[2], qr[3])\n",
    "        theCircuit.x(qr[3])\n",
    "        theCircuit.u1(pi/2.0, qr[2])\n",
    "        theCircuit.x(qr[2])\n",
    "        theCircuit.z(qr[2])\n",
    "        theCircuit.cx(qr[2], qr[3])\n",
    "        theCircuit.cx(qr[3], qr[2])\n",
    "        theCircuit.h(qr[2])\n",
    "        theCircuit.h(qr[3])\n",
    "        theCircuit.x(qr[3])\n",
    "        theCircuit = cu1pi2(theCircuit, qr[2], qr[3])\n",
    "        theCircuit.x(qr[2])\n",
    "        theCircuit.cz(qr[2], qr[3])\n",
    "        theCircuit.x(qr[2])\n",
    "        theCircuit.x(qr[3])\n",
    "        \n",
    "    elif idx == 2:\n",
    "        theCircuit.x(qr[2])\n",
    "        theCircuit.x(qr[3])\n",
    "        theCircuit.cz(qr[2], qr[3])\n",
    "        theCircuit.x(qr[3])\n",
    "        theCircuit.u1(pi/2.0, qr[3])\n",
    "        theCircuit.cx(qr[2], qr[3])\n",
    "        theCircuit.h(qr[2])\n",
    "        theCircuit.h(qr[3])\n",
    "\n",
    "    elif idx == 3:\n",
    "        theCircuit.cx(qr[3], qr[2])\n",
    "        theCircuit.x(qr[3])\n",
    "        theCircuit.h(qr[3])\n",
    "        \n",
    "    #measure the third and fourth qubits in the computational basis\n",
    "    theCircuit.measure(qr[2], cr[2])\n",
    "    theCircuit.measure(qr[3], cr[3])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### A quantum program for one round of the game\n",
    "\n",
    "Prior to the start of the game, Alice and Bob share the entangled quantum states as described before. Notice that this is performed before their receiving inputs. After sharing entanglement, they are not allowed to communicate. Next, an integer $a$ is given to Alice, and $b$ to Bob. Alice and Bob then independently perform operations with one the circuits defined previously based on their inputs. They generate their answers (three bits each) based on their measurement outcomes so that the parity of Alice's answer is even, and Bob's answer is odd. Here is a program for one round of the game using the circuits previously defined. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The values of a and b are, resp., 3 1\n",
      "{'0110': 1}\n",
      "Alice answer for a =  3 is [0, 1, 1]\n",
      "Bob answer for b =  1 is [1, 0, 0]\n",
      "Alice and Bob won\n"
     ]
    }
   ],
   "source": [
    "a, b = random.randint(1,3), random.randint(1,3) #generate random integers\n",
    "print(\"The values of a and b are, resp.,\", a,b)\n",
    "aliceCircuit = aliceCircuits[\"Alice\"+str(a)]\n",
    "bobCircuit = bobCircuits[\"Bob\"+str(b)]\n",
    "circuitName = \"Alice\"+str(a)+\"Bob\"+str(b)\n",
    "circuitName = sharedEntangled+aliceCircuit+bobCircuit\n",
    "\n",
    "# Use local qasm simulator\n",
    "backend = Aer.get_backend(\"qasm_simulator\")\n",
    "\n",
    "# Use the IBMQ Quantum Experience\n",
    "# backend = least_busy(IBMQ.backends())\n",
    "\n",
    "shots = 1 # We perform a one-shot experiment\n",
    "results = execute([circuitName], backend=backend, shots=shots).result()\n",
    "answer = results.get_counts(circuitName)\n",
    "print(answer)\n",
    "for key in answer.keys():\n",
    "    aliceAnswer = [int(key[-1]), int(key[-2])]\n",
    "    bobAnswer   = [int(key[-3]), int(key[-4])]\n",
    "    if sum(aliceAnswer) % 2 == 0:#the sume of Alice answer must be even\n",
    "        aliceAnswer.append(0) \n",
    "    else:\n",
    "        aliceAnswer.append(1)\n",
    "    if sum(bobAnswer) % 2 == 1:#the sum of Bob answer must be odd\n",
    "        bobAnswer.append(0)   \n",
    "    else:\n",
    "        bobAnswer.append(1)\n",
    "    break\n",
    "\n",
    "print(\"Alice answer for a = \", a, \"is\", aliceAnswer)\n",
    "print(\"Bob answer for b = \", b, \"is\", bobAnswer)\n",
    "\n",
    "if(aliceAnswer[b-1] != bobAnswer[a-1]): #check if the intersection of their answers is the same\n",
    "    print(\"Alice and Bob lost\")\n",
    "else:\n",
    "    print(\"Alice and Bob won\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Checking Alice's and Bob's answers for all combinations of their inputs\n",
    "\n",
    "Finally, we can try every combination of $a$ and $b$ to see that Alice and Bob can always win surely. One can also try to run the code below with `IBMQ` backend and check that the winning probability can be higher than $8/9$ on real devices (unfortunately, perfect probability cannot be achieved due to noise and gate errors)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Asking Alice and Bob with a and b are, resp., 1 1\n",
      "\t#wins =  10 out of  10 shots\n",
      "Asking Alice and Bob with a and b are, resp., 1 2\n",
      "\t#wins =  10 out of  10 shots\n",
      "Asking Alice and Bob with a and b are, resp., 1 3\n",
      "\t#wins =  10 out of  10 shots\n",
      "Asking Alice and Bob with a and b are, resp., 2 1\n",
      "\t#wins =  10 out of  10 shots\n",
      "Asking Alice and Bob with a and b are, resp., 2 2\n",
      "\t#wins =  10 out of  10 shots\n",
      "Asking Alice and Bob with a and b are, resp., 2 3\n",
      "\t#wins =  10 out of  10 shots\n",
      "Asking Alice and Bob with a and b are, resp., 3 1\n",
      "\t#wins =  10 out of  10 shots\n",
      "Asking Alice and Bob with a and b are, resp., 3 2\n",
      "\t#wins =  10 out of  10 shots\n",
      "Asking Alice and Bob with a and b are, resp., 3 3\n",
      "\t#wins =  10 out of  10 shots\n",
      "Number of Games =  90\n",
      "Number of Wins =  90\n",
      "Winning probabilities =  100.0\n"
     ]
    }
   ],
   "source": [
    "# Use local qasm simulator\n",
    "backend = Aer.get_backend(\"qasm_simulator\")\n",
    "\n",
    "# Use the IBMQ Quantum Experience\n",
    "# backend = backend = least_busy(IBMQ.backends())\n",
    "\n",
    "shots = 10 # We perform 10 shots of experiments for each round\n",
    "nWins = 0\n",
    "nLost = 0\n",
    "for a in range(1,4):\n",
    "    for b in range(1,4):\n",
    "        print(\"Asking Alice and Bob with a and b are, resp.,\", a,b)\n",
    "        rWins = 0\n",
    "        rLost = 0\n",
    "        \n",
    "        aliceCircuit = aliceCircuits[\"Alice\"+str(a)]\n",
    "        bobCircuit = bobCircuits[\"Bob\"+str(b)]\n",
    "        circuitName = \"Alice\"+str(a)+\"Bob\"+str(b)\n",
    "        circuitName = sharedEntangled+aliceCircuit+bobCircuit\n",
    "        \n",
    "\n",
    "        if backend in IBMQ.backends(filters=lambda x: x.name()):\n",
    "            IBMQ_backend = backend.configuration()\n",
    "            IBMQ_coupling = backend.configuration()['coupling_map']\n",
    "            results = execute([circuitName], backend=backend, shots=shots, coupling_map=IBMQ_coupling, max_credits=3)\n",
    "        else:\n",
    "            results = execute([circuitName], backend=backend, shots=shots)\n",
    "        answer = results.result().get_counts(circuitName)\n",
    "\n",
    "        for key in answer.keys():\n",
    "            kfreq = answer[key] #frequencies of keys obtained from measurements\n",
    "            aliceAnswer = [int(key[-1]), int(key[-2])]\n",
    "            bobAnswer   = [int(key[-3]), int(key[-4])]\n",
    "            if sum(aliceAnswer) % 2 == 0:\n",
    "                aliceAnswer.append(0)\n",
    "            else:\n",
    "                aliceAnswer.append(1)\n",
    "            if sum(bobAnswer) % 2 == 1:\n",
    "                bobAnswer.append(0)\n",
    "            else:\n",
    "                bobAnswer.append(1)\n",
    "\n",
    "            #print(\"Alice answer for a = \", a, \"is\", aliceAnswer)\n",
    "            #print(\"Bob answer for b = \", b, \"is\", bobAnswer)\n",
    "        \n",
    "            if(aliceAnswer[b-1] != bobAnswer[a-1]):\n",
    "                #print(a, b, \"Alice and Bob lost\")\n",
    "                nLost += kfreq\n",
    "                rLost += kfreq\n",
    "            else:\n",
    "                #print(a, b, \"Alice and Bob won\")\n",
    "                nWins += kfreq\n",
    "                rWins += kfreq\n",
    "        print(\"\\t#wins = \", rWins, \"out of \", shots, \"shots\")\n",
    "\n",
    "print(\"Number of Games = \", nWins+nLost)\n",
    "print(\"Number of Wins = \", nWins)\n",
    "print(\"Winning probabilities = \", (nWins*100.0)/(nWins+nLost))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## About Quantum Pseudo-Telepathy for the Magic Square Game"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "The winning strategy described in this note is from [Brassard et al. 2004](https://arxiv.org/abs/quant-ph/0407221), where there listed many other interesting games that can be accomplished with shared entanglement. The Magic Square game was first proposed by [Aravind, 2002](https://arxiv.org/abs/quant-ph/0206070) based on the work of [Mermin, 1990](http://blog.umd.edu/phil858/files/2015/10/Mermin1990-2jvtdbh.pdf) and [Peres, 1990](http://blog.umd.edu/phil858/files/2015/10/Peres1990-2g8uzi6.pdf).\n",
    "\n",
    "[Gawron et al., 2008](https://arxiv.org/pdf/0801.4848v1.pdf) showed that the winning probabilities of Magic Square Games is related to the noise of the circuits. [Ozaydin, 2016](https://arxiv.org/abs/1609.03881) provided theoretical analysis of the winning probabilities of the thermal entangled state of the spin system for the Magic Square game: the higher the temperature, the lower the winning probability. Interestingly, [Pawela et al. 2013](http://journals.plos.org/plosone/article?id=10.1371/journal.pone.0064694) showed that it is possible to achieve higher winning probability under noisy circuits by employing Semidefinite Programming for noise mitigation.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
